/**
 * ReportGear(2011)
 */
package net.abbp.report.view.cell.painter;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.List;

import net.abbp.core.util.StringUtils;
import net.abbp.report.model.cell.style.FontStyle;
import net.abbp.report.model.cell.style.Style;
import net.abbp.report.model.cell.style.TextStyle;

import com.reportgear.report.core.api.compare.ComparatorUtils;
import com.reportgear.report.model.cell.style.format.FormatterFactory;
import com.reportgear.report.view.grid.util.GraphHelper;

/**
 * 单元格绘制实用类
 * 
 * @version 1.0 2011-4-17
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
public class CellPaintUtils {
    // 格式化器
    private static FormatterFactory formatterFactory = FormatterFactory.INSTANCE;

    /**
     * 绘制格式化字符串
     * 
     * @param g2
     *            图形对象
     * @param rect
     *            绘制区域
     * @param content
     *            内容
     * @param style
     *            样式
     */
    public static void paintCellStyleString(Graphics2D g2, Rectangle rect, String str, Style style) {
        double w = rect.width;
        double h = rect.height;
        String content = str;

        if (StringUtils.isEmpty(content)) {
            return;
        }

        if (style == null) {
            style = Style.DEFAULT_STYLE;
        }

        if (!StringUtils.isEmpty(style.getFormatterKey())) {
            content = formatterFactory.getFormatterByKey(style.getFormatterKey()).format(content);
        }

        List<String> lines = getLineTextList(content, style, rect.width);

        g2.getFontRenderContext();
        FontStyle font = style.getFontStyle();

        // Locale locale = ReportContext.getLocale();
        // if ((Locale.ENGLISH.equals(locale)) && (((str.startsWith("↓")) ||
        // (str.startsWith("→"))))) {
        // font = ReportFont.getInstance("Dialog", font.getStyle(),
        // font.getSize());
        // }
        if (!ComparatorUtils.equals(font, g2.getFont())) {
            g2.setFont(font);
        }
        Color color = font.getForeground();
        if (!ComparatorUtils.equals(color, g2.getPaint())) {
            g2.setPaint(color);
        }
        FontMetrics fm = g2.getFontMetrics();

        int count = lines.size();
        if (count == 0) {
            return;
        }

        Shape oldClip = g2.getClip();
        g2.clip(rect);
        g2.translate(rect.x, rect.y);

        double textH = fm.getHeight();
        double startY;
        switch (style.getVerticalAlignment()) {
        case Middle:
            startY = (h + style.getSpacingBefore() - textH * count - style.getSpacingAfter()) / 2.0D;
            break;
        case Top:
            startY = style.getSpacingBefore();
            break;
        case Bottom:
            startY = h - textH * count - style.getSpacingAfter();
            break;
        default:
            startY = (h - textH * count) / 2.0D;
        }

        for (int i = 0; i < count; i++) {
            String tmpStr = lines.get(i).trim();
            GraphHelper.drawString(g2, tmpStr, getDrawStringX(w, fm.stringWidth(tmpStr), style), startY + textH * i
                    + fm.getAscent());
        }
        g2.translate(-rect.x, -rect.y);
        g2.setClip(oldClip);
    }

    /**
     * 绘制格式化字符串
     * 
     * @param g2
     *            图形对象
     * @param rect
     *            绘制区域
     * @param content
     *            内容
     * @param style
     *            样式
     */
    public static void paintCellStyleString(Graphics2D g2, Rectangle rect, String str, Style style, int offsetY) {
        double w = rect.width;
        double h = rect.height;
        String content = str;

        if (StringUtils.isEmpty(content)) {
            return;
        }

        if (style == null) {
            style = Style.DEFAULT_STYLE;
        }

        if (!StringUtils.isEmpty(style.getFormatterKey())) {
            content = formatterFactory.getFormatterByKey(style.getFormatterKey()).format(content);
        }

        List<String> lines = getLineTextList(content, style, rect.width);

        g2.getFontRenderContext();
        FontStyle font = style.getFontStyle();

        // Locale locale = ReportContext.getLocale();
        // if ((Locale.ENGLISH.equals(locale)) && (((str.startsWith("↓")) ||
        // (str.startsWith("→"))))) {
        // font = ReportFont.getInstance("Dialog", font.getStyle(),
        // font.getSize());
        // }
        if (!ComparatorUtils.equals(font, g2.getFont())) {
            g2.setFont(font);
        }
        Color color = font.getForeground();
        if (!ComparatorUtils.equals(color, g2.getPaint())) {
            g2.setPaint(color);
        }
        FontMetrics fm = g2.getFontMetrics();

        int count = lines.size();
        if (count == 0) {
            return;
        }

        Shape oldClip = g2.getClip();
        g2.clip(rect);
        g2.translate(rect.x, rect.y);

        double textH = fm.getHeight();
        double startY;
        switch (style.getVerticalAlignment()) {
        case Middle:
            startY = (h + style.getSpacingBefore() - textH * count - style.getSpacingAfter()) / 2.0D;
            break;
        case Top:
            startY = style.getSpacingBefore();
            break;
        case Bottom:
            startY = h - textH * count - style.getSpacingAfter();
            break;
        default:
            startY = (h - textH * count) / 2.0D;
        }

        for (int i = 0; i < count; i++) {
            String tmpStr = lines.get(i).trim();
            GraphHelper.drawString(g2, tmpStr, getDrawStringX(w, fm.stringWidth(tmpStr), style), startY + textH * i
                    + fm.getAscent());
        }
        g2.translate(-rect.x, -rect.y);
        g2.setClip(oldClip);
    }

    /**
     * 字符串自动分行时，根据宽度对字符进行分割
     * 
     * @param text
     *            显示的字符串
     * @param style
     *            样式
     * @param width
     *            宽度
     * @return 分割后的字符串列表
     */
    public static List getLineTextList(String text, Style style, double width) {
        List lineList = new ArrayList();
        if ((text == null) || (text.length() <= 0)) {
            return lineList;
        }
        if (style == null) {
            style = Style.DEFAULT_STYLE;
        }
        // //旋转字符串不处理
        // if (style.getRotation() != 0) {
        // lineList.add(text);
        // return lineList;
        // }
        FontStyle font = style.getFontStyle();
        FontMetrics fm = GraphHelper.getFontMetrics(font);

        // 如果不是自动换行，查找里面是否有换行符,根据换行符换行
        if (style.getTextStyle() != TextStyle.WordWrap) {
            StringBuffer buffer1 = new StringBuffer();
            for (int i = 0; i < text.length(); i++) {
                char c = text.charAt(i);
                if (c == '\\') {
                    if ((i < text.length() - 1) && (text.charAt(i + 1) == 'n')) {
                        ++i;
                        lineList.add(buffer1.toString());
                        buffer1.delete(0, buffer1.length());
                    } else {
                        buffer1.append(c);
                    }
                } else if (c == '\n') {
                    lineList.add(buffer1.toString());
                    buffer1.delete(0, buffer1.length());
                } else {
                    buffer1.append(c);
                }
            }
            if (buffer1.length() > 0) {
                lineList.add(buffer1.toString());
                buffer1.delete(0, buffer1.length());
            }
            return lineList;
        }

        // 自动计算换行
        double textWidth = width - style.getPaddingLeft() - style.getPaddingRight();
        int j = 0;
        StringBuffer buffer2 = new StringBuffer();
        StringBuffer buffer3 = new StringBuffer();
        int tempWidth = 0;
        for (int i = 0; i < text.length(); i++) {
            if ((i > 0) && (Character.isLetter(text.charAt(i))) && (Character.isLetter(text.charAt(i - 1)))) {
                if (tempWidth + fm.charWidth(text.charAt(i)) > textWidth) {
                    if (j > 0) {
                        lineList.add(buffer2.toString());
                        buffer2.delete(0, buffer2.length());
                        j = 0;
                    }
                    lineList.add(buffer3.toString());
                    buffer3.delete(0, buffer3.length());
                    tempWidth = 0;
                }
                buffer3.append(text.charAt(i));
                tempWidth += fm.charWidth(text.charAt(i));
            } else if (text.charAt(i) == '\n') {
                if ((j + tempWidth > textWidth) && (buffer2.length() > 0)) {
                    lineList.add(buffer2.toString());
                    lineList.add(buffer3.toString());
                } else {
                    buffer2.append(buffer3);
                    lineList.add(buffer2.toString());
                }
                buffer2.delete(0, buffer2.length());
                j = 0;
                buffer3.delete(0, buffer3.length());
                tempWidth = 0;
            } else if ((text.charAt(i) == '\\') && (i < text.length() - 1) && (text.charAt(i + 1) == 'n')) {
                ++i;
                if ((j + tempWidth > textWidth) && (buffer2.length() > 0)) {
                    lineList.add(buffer2.toString());
                    lineList.add(buffer3.toString());
                } else {
                    buffer2.append(buffer3);
                    lineList.add(buffer2.toString());
                }
                buffer2.delete(0, buffer2.length());
                j = 0;
                buffer3.delete(0, buffer3.length());
                tempWidth = 0;
            } else {
                if ((text.charAt(i) == '\\') && (i + 1 < text.length()) && (text.charAt(i + 1) == '\\')) {
                    ++i;
                }
                if ((j + tempWidth > textWidth) && (buffer2.length() > 0)) {
                    lineList.add(buffer2.toString());
                    buffer2.delete(0, buffer2.length());
                    j = 0;
                }
                buffer2.append(buffer3);
                j += tempWidth;
                buffer3.delete(0, buffer3.length());
                tempWidth = 0;
                buffer3.append(text.charAt(i));
                tempWidth = fm.charWidth(text.charAt(i));
            }
        }
        if ((j + tempWidth > textWidth) && (buffer2.length() > 0)) {
            lineList.add(buffer2.toString());
            lineList.add(buffer3.toString());
        } else {
            buffer2.append(buffer3);
            lineList.add(buffer2.toString());
        }
        return lineList;
    }

    /**
     * 获取字符串绘制的X位置
     * 
     * @param totalWidth
     *            总宽度
     * @param stringWidth
     *            字符串宽度
     * @param style
     *            样式
     * @return X位置
     */
    private static double getDrawStringX(double totalWidth, double stringWidth, Style style) {
        switch (style.getHorizentalAlignment()) {
        case Center:
            return (totalWidth + style.getPaddingLeft() - stringWidth - style.getPaddingRight()) / 2.0D;
        case Left:
            return style.getPaddingLeft();
        case Right:
            return totalWidth - stringWidth - style.getPaddingRight();
        default:
            return (totalWidth + style.getPaddingLeft() - stringWidth - style.getPaddingRight()) / 2.0D;
        }
    }
}
